package com.dispacher.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

public abstract class MethodUtil {

	@SuppressWarnings("unchecked")
	private static Map<Class, Map<String, Method>> container = new HashMap<Class, Map<String, Method>>();

	public static Object invoke(Method method, Object instance, Object[] params) {
		try {
			if (method.getGenericParameterTypes() != null && method.getGenericParameterTypes().length > 0) {
				Type type = method.getGenericParameterTypes()[0];
				if (type.equals(Long.class)) {
					return method.invoke(instance, new Object[] { Long.valueOf((String) params[0]) });
				}
				if (type.equals(Integer.class)) {
					return method.invoke(instance, new Object[] { Integer.valueOf((String) params[0]) });
				}
				if (type.equals(Double.class)) {
					return method.invoke(instance, new Object[] { Double.valueOf((String) params[0]) });
				}
				if (type.equals(Float.class)) {
					return method.invoke(instance, new Object[] { Float.valueOf((String) params[0]) });
				}
			}
			return method.invoke(instance, params);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Object invoke(String methodName, Object instance, Object[] params) {
		return invoke(findMethod(methodName, instance.getClass()), instance, params);
	}

	@SuppressWarnings("unchecked")
	public static Method findMethod(String methodName, Class cla) {
		methodName = methodName.toUpperCase();
		if (container.containsKey(cla)) {
			return container.get(cla).get(methodName);
		}
		Map<String, Method> _temp = new HashMap<String, Method>();
		Method[] methods = cla.getDeclaredMethods();
		for (Method method : methods) {
			String key = method.getName().toUpperCase();
			_temp.put(key, method);
		}
		container.put(cla, _temp);
		return _temp.get(methodName);
	}
}
